package com.github.defense.plugin.gray.instance;


import com.github.defense.plugin.gray.context.GrayLocalContext;
import com.github.defense.plugin.gray.decision.predicate.DecisionDefinition;
import com.github.defense.plugin.gray.decision.predicate.PolicyDefinition;
import com.github.defense.plugin.gray.decision.predicate.PolicyInfo;
import com.github.defense.plugin.gray.decision.predicate.PolicyPredicate;
import com.github.defense.plugin.gray.holder.DecisionDefinitionHolder;
import com.github.defense.plugin.gray.holder.MetaDataHolder;
import com.github.defense.plugin.gray.manager.GrayDecisionManager;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 实例区分
 *
 * @Author: lettger
 * @Date: 2021/6/18 1:25 下午
 */
@Slf4j
public class DefaultGrayInstanceSorter implements GrayInstanceSorter {

    private GrayLocalContext localContext;

    private PolicyPredicate predicate;

    private GrayDecisionManager decisionManager;

    public DefaultGrayInstanceSorter(GrayLocalContext localContext, PolicyPredicate predicate, GrayDecisionManager decisionManager) {
        this.localContext = localContext;
        this.predicate = predicate;
        this.decisionManager = decisionManager;
    }

    /**
     * 区分出灰度实例和正常实例
     * 1. 从metadata中构造出灰度策略和灰度决策(一个策略包含多个决策信息)
     * 2. 过滤灰度服务 核心
     *
     * @param instances
     * @return
     */
    @Override
    public GrayInstanceList sorter(List<GrayInstance> instances) {
        List grayInstance = Lists.newArrayList();
        List<GrayInstance> grayInstances = filterGrayInstance(instances);
        if (!CollectionUtils.isEmpty(grayInstances)) {
            // 进行灰度决策
            grayInstances = filterDecisions(grayInstances);
            if (!CollectionUtils.isEmpty(grayInstances)) {
                grayInstance = grayInstances.stream().map(res -> res.getServer()).collect(Collectors.toList());
            }
        }
        List normalInstance = Lists.newArrayList();
        List<GrayInstance> normalInstances = filterNormalInstance(instances);
        if (!CollectionUtils.isEmpty(normalInstances)) {
            normalInstance = normalInstances.stream().map(res -> res.getServer()).collect(Collectors.toList());
        }
        return new GrayInstanceList<>(grayInstance, normalInstance);
    }


    @Override
    public List<GrayInstance> filterDecisions(List<GrayInstance> instances) {
        List<PolicyInfo> list = Lists.newArrayList();
        for (GrayInstance instance : instances) {
            PolicyInfo policyInfo = new PolicyInfo();
            policyInfo.setInstance(instance);
            policyInfo.setMetadata(MetaDataHolder.getGrayMetaData(instance.getMetadata()));
            list.add(policyInfo);
        }
        // 构造DecisionDefinition集合对象
        List<DecisionDefinition> definitions = DecisionDefinitionHolder.getDecisionDefinitions(list);
        if (!CollectionUtils.isEmpty(definitions)) {
            List<PolicyDefinition> decisions = decisionManager.getPolicies(definitions);
            if (!CollectionUtils.isEmpty(decisions)) {
                return predicate.test(decisions,localContext.getGrayRequest());
            }
        }
        return null;
    }
}
